package com.zly.framework.rbac.filter;

import com.zly.framework.rbac.configuration.SysAuthConfiguration;
import com.zly.framework.rbac.utils.JwtUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
public class JwtFilter extends BasicAuthenticationFilter {

    private JwtUtils jwtUtils;
    private SysAuthConfiguration sysAuthConfiguration;
    private RedisTemplate<String, String> redisTemplate;

    public JwtFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    public JwtFilter(AuthenticationManager authenticationManager,
                     RedisTemplate<String, String> redisTemplate,
                     SysAuthConfiguration sysAuthConfiguration,
                     JwtUtils jwtUtils) {
        super(authenticationManager);
        this.redisTemplate = redisTemplate;
        this.jwtUtils = jwtUtils;
        this.sysAuthConfiguration = sysAuthConfiguration;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String REDIS_PREFIX = "user:";
        String TOKEN_HEADER = sysAuthConfiguration.getJwt().getHeader();
        String token = request.getHeader(TOKEN_HEADER);
        if (!StringUtils.hasText(token)) {
            chain.doFilter(request, response);
            return;
        }
        String username = jwtUtils.getUsername(token);
        String REDIS_KEY = REDIS_PREFIX + username;
        for (Object userToken : Objects.requireNonNull(redisTemplate.opsForList().range(REDIS_KEY, 0, -1))) {
            if (userToken.equals(token)) {
                List<String> grantedStrings = jwtUtils.getPermission(token);
                ArrayList<GrantedAuthority> grantedAuthorities = new ArrayList<>();
                if (grantedStrings != null) {
                    for (String grantedString : grantedStrings) {
                        grantedAuthorities.add(new SimpleGrantedAuthority(grantedString));
                    }
                }
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(username, token, grantedAuthorities);
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                break;
            }
        }
        chain.doFilter(request, response);
    }


}
